package questionComponents;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;

import javax.swing.JColorChooser;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

import org.nfunk.jep.JEP;

public class Calculator extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private DrawPanel drawPanel;
	public int height = 20;

	public Point pMouse = new Point();

	public Calculator() {
		setLayout(null);
		setSize(500, 520);
		drawPanel = new DrawPanel();
		drawPanel.setBounds(0, 20, getWidth(), 500);
		add(drawPanel);
		addMouseWheelListener(new MouseWheelListener() {
			public void mouseWheelMoved(MouseWheelEvent e) {
				drawPanel.zoom -= e.getWheelRotation();
				if (drawPanel.zoom <= 0.0D) {
					drawPanel.zoom = 1.0D;
				} else if (drawPanel.zoom >= 100.0D) {
					drawPanel.zoom = 100.0D;
				} else {
					drawPanel.paint();
				}
			}
		});
		addMouseMotionListener(new MouseMotionListener() {
			public void mouseMoved(MouseEvent e) {
				Calculator.this.pMouse = e.getPoint();
			}

			public void mouseDragged(MouseEvent e) {
				drawPanel.offset.x = (drawPanel.offset.x
						- Calculator.this.pMouse.x + e.getX());
				drawPanel.offset.y = (drawPanel.offset.y
						- Calculator.this.pMouse.y + e.getY());
				pMouse = e.getPoint();
				drawPanel.paint();
			}
		});
	}

	class DrawPanel extends JPanel {
		private static final long serialVersionUID = 1L;
		public ArrayList<Equation> Equations = new ArrayList<Equation>();
		public Point offset = new Point();
		public double zoom = 10.0D;
		public boolean displayGrid = false;
		public boolean displaySlope = false;
		public Point origin = new Point();

		public DrawPanel() {
			setBackground(Color.white);
			offset.x = 0;
			offset.y = 0;
			setDoubleBuffered(true);
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			origin.x = (getWidth() / 2);
			origin.y = (getHeight() / 2);
			Graphics2D g2d = (Graphics2D) g;
			g2d.setColor(Color.gray);
			if (this.displayGrid) {
				for (double x = (-origin.x - offset.x) / zoom; x < (origin.x - offset.x)
						/ zoom; x += 0.01D) {
					if ((this.displayGrid) && (x % 1.0D < 0.01D)
							&& (x % 1.0D > -0.01D)) {
						double xA = x * zoom;
						g2d.drawLine((int) (origin.x + xA + offset.x), 0,
								(int) (origin.x + xA + offset.x), getHeight());
					}
				}
				for (double y = (-origin.y - offset.y) / zoom; y < (origin.y - offset.y)
						/ this.zoom; y += 0.01D) {
					if ((this.displayGrid) && (y % 1.0D < 0.01D)
							&& (y % 1.0D > -0.01D)) {
						double yA = y * this.zoom;
						g2d.drawLine(0, (int) (origin.y + yA + offset.y),
								getHeight(),
								(int) (origin.y + yA + this.offset.y));
					}
				}
			}
			g2d.setColor(Color.black);
			float width = 5.0F;
			g2d.setStroke(new BasicStroke(width));
			g2d.drawLine(getWidth() / 2 + this.offset.x, 0, getWidth() / 2
					+ this.offset.x, getHeight());
			g2d.drawLine(0, getHeight() / 2 + this.offset.y, getWidth(),
					getHeight() / 2 + this.offset.y);
			width = 3.0F;
			g2d.setColor(Color.darkGray);
			g2d.setStroke(new BasicStroke(width));
			for (int a = 0; a < this.Equations.size(); a++) {
				Equation equation = (Equation) this.Equations.get(a);
				g2d.setColor(equation.getColor());
				double pX = 1000.0D;
				double pY = 0.0D;
				for (double x = (-origin.x - this.offset.x - this.zoom)
						/ this.zoom; x < (origin.x - this.offset.x + this.zoom)
						/ this.zoom; x += 0.1D) {
					equation.myParser.addVariable("x", x);
					double y = equation.myParser.getValue();
					y *= this.zoom;
					double xA = x * this.zoom;
					if (pX != 1000.0D) {
						g2d.drawLine((int) (origin.x + pX + this.offset.x),
								(int) (origin.y - pY + this.offset.y),
								(int) (origin.x + xA + this.offset.x),
								(int) (origin.y - y + this.offset.y));
					}
					pX = xA;
					pY = y;
				}
			}
		}

		public void newEquation(Equation equation) {
			Equations.add(equation);
			paintComponent(getGraphics());
		}

		public void paint() {
			paintComponent(getGraphics());
		}
	}

	public class Equation extends JPanel {
		private static final long serialVersionUID = 1L;
		JTextField userEquation;
		public JEP myParser;
		final JPanel colorPanel;

		Equation() {
			this.myParser = new JEP();
			setLayout(null);
			this.userEquation = new JTextField();
			this.userEquation.setToolTipText("Enter your equation here");
			this.userEquation.setBounds(30, 0, 450, 16);
			add(this.userEquation);
			this.myParser.addStandardConstants();
			this.myParser.addStandardFunctions();
			this.myParser.addComplex();
			this.myParser.setAllowUndeclared(true);
			this.myParser.setImplicitMul(true);
			this.myParser.setAllowAssignment(true);
			this.myParser.addVariable("x", 0.0D);
			this.userEquation.addCaretListener(new CaretListener() {
				public void caretUpdate(CaretEvent arg0) {
					Equation.this.myParser
							.parseExpression(Equation.this.userEquation
									.getText());
					drawPanel.paint();
				}
			});
			this.colorPanel = new JPanel();
			this.colorPanel.setBounds(10, 3, 10, 10);
			this.colorPanel.setBackground(Color.BLACK);
			add(this.colorPanel);
			this.colorPanel
					.setToolTipText("Sets the color of the line on the graph");
			this.colorPanel.addMouseListener(new MouseListener() {
				public void mouseReleased(MouseEvent arg0) {
				}

				public void mousePressed(MouseEvent arg0) {
				}

				public void mouseExited(MouseEvent arg0) {
				}

				public void mouseEntered(MouseEvent arg0) {
				}

				public void mouseClicked(MouseEvent arg0) {
					Color color = JColorChooser.showDialog(new JPanel(),
							"Choose Color",
							Equation.this.colorPanel.getBackground());
					Equation.this.colorPanel.setBackground(color);
					drawPanel.paint();
				}
			});
		}

		public Color getColor() {
			return this.colorPanel.getBackground();
		}
	}
}